package com.hsl.study.controller;

import cn.hutool.core.util.ObjectUtil;
import com.hsl.study.dto.UserPointsReq;
import com.hsl.study.dto.UserRanking;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * zadd user:randing 100 user1  200 user2 300 user3   添加数据
 * <p>
 * zrange user:ranking  0 -1 withscores  查看数据带分数  withscores  从低到高
 * <p>
 * zrevrange user:ranking 0 2 withscores  从高到低  前三名
 * <p>
 * 分数相同时  用积分+（1- 时间戳/10的13次方） System.currentTimeMillis()/ 1e13
 * <p>
 * 时间戳获得方式 new Date().getTime() 不建议 因为new的对象需要GC
 * <p>
 * 建议使用System.currentTimeMillis()
 */
@RestController
public class UserRankingController {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final String REDIS_RANKING_KEY = "user:ranking";

    @PostMapping("/addUserPoint")
    public boolean addUserPoint(@RequestBody List<UserPointsReq> userPointsReqs) {


        for (UserPointsReq userPointsReq : userPointsReqs) {
            String userId = userPointsReq.getUserId();

            double score = userPointsReq.getPoints() + (1 - userPointsReq.getUpdateTime() / 1e13);

            this.stringRedisTemplate.opsForZSet().add(REDIS_RANKING_KEY, userId, score);
        }
        return true;
    }

    @PostMapping("/addOneUserPoint/{userId}")
    public boolean addOneUserPoint(@PathVariable("userId") String userId) {
        Double score = stringRedisTemplate.boundZSetOps(REDIS_RANKING_KEY).score(userId);
//        if (ObjectUtil.isEmpty(score)) {
//            score = 1 + (1 - System.currentTimeMillis() / 1e13);
//        } else {
//            String scoreStr = String.valueOf(score);
//            String substring = scoreStr.substring(0, scoreStr.indexOf('.'));
//            score = Double.parseDouble(substring) + (1 - System.currentTimeMillis() / 1e13) + 1;
//        }
        score = ObjectUtil.isEmpty(score)
                ? 1 + (1 - System.currentTimeMillis() / 1e13)
                : Double.parseDouble(String.valueOf(score).substring(0, String.valueOf(score).indexOf('.'))) + (1 - System.currentTimeMillis() / 1e13) + 1;

        this.stringRedisTemplate.opsForZSet().add(REDIS_RANKING_KEY, userId, score);
        return true;
    }

    @GetMapping("/userRankings")
    public List<UserRanking> userRankings(@RequestParam("topN") int topN) {

        Set<ZSetOperations.TypedTuple<String>> typedTuples = this.stringRedisTemplate.opsForZSet().reverseRangeWithScores(REDIS_RANKING_KEY, 0, topN - 1);
        List<UserRanking> userRankingList = new ArrayList<>();

        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            UserRanking userRanking = new UserRanking();
            userRanking.setUserId(typedTuple.getValue());
            userRanking.setRedisScore(typedTuple.getScore());
            userRankingList.add(userRanking);
        }
        return userRankingList;
    }
}
